package com.xh.chat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xh.chat.enums.MsgSignFlagEnum;
import com.xh.chat.enums.SearchFriendsStatusEnum;
import com.xh.chat.mapper.ChatMsgMapper;
import com.xh.chat.mapper.FriendsRequestMapper;
import com.xh.chat.mapper.MyFriendsMapper;
import com.xh.chat.mapper.UserMapper;
import com.xh.chat.model.table.ChatMsg;
import com.xh.chat.model.table.FriendsRequest;
import com.xh.chat.model.table.MyFriend;
import com.xh.chat.model.table.User;
import com.xh.chat.model.vo.FriendRequestVO;
import com.xh.chat.model.vo.MyFriendsVO;
import com.xh.chat.netty.dto.ChatMsgDTO;
import com.xh.chat.netty.dto.DataContentDTO;
import com.xh.chat.netty.enums.MsgActionEnum;
import com.xh.chat.netty.utils.ChannelUtil;
import com.xh.chat.service.UserService;
import com.xh.chat.utils.FileUtils;
import com.xh.chat.utils.JsonUtils;
import com.xh.chat.utils.QRCodeUtils;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MyFriendsMapper myFriendsMapper;

    @Autowired
    private FriendsRequestMapper friendsRequestMapper;

    @Autowired
    private ChatMsgMapper chatMsgMapper;

    @Autowired
    private QRCodeUtils qrCodeUtils;

//	@Autowired
//	private FastDFSClient fastDFSClient;

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public boolean queryUsernameIsExist(String username) {
        LambdaQueryWrapper<User> eq = Wrappers.lambdaQuery(User.class).eq(User::getUsername, username);
        User result = userMapper.selectOne(eq);
        return result != null;
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public User queryUserForLogin(String username, String pwd) {
        LambdaQueryWrapper<User> eq = Wrappers.lambdaQuery(User.class)
                .eq(User::getUsername, username)
                .eq(User::getPassword, pwd);
        return userMapper.selectOne(eq);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public User saveUser(User user) {
        long userId = IdWorker.getId();
        // 为每个用户生成一个唯一的二维码
        String qrCodePath = "C://user" + userId + "qrcode.png";
        // muxin_qrcode:[username]
        qrCodeUtils.createQRCode(qrCodePath, "muxin_qrcode:" + user.getUsername());
        MultipartFile qrCodeFile = FileUtils.fileToMultipart(qrCodePath);
        String qrCodeUrl = "";
//		try {
//			qrCodeUrl = fastDFSClient.uploadQRCode(qrCodeFile);
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
        user.setQrCode("qrCodeUrl");
        user.setId(userId);
        userMapper.insert(user);
        return user;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public User updateUserInfo(User user) {
        userMapper.updateById(user);
        return userMapper.selectById(user.getId());
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Integer preconditionSearchFriends(Long myUserId, String friendUsername) {
        User user = queryUserInfoByUsername(friendUsername);
        // 1. 搜索的用户如果不存在，返回[无此用户]
        if (user == null) {
            return SearchFriendsStatusEnum.USER_NOT_EXIST.getStatus();
        }
        // 2. 搜索账号是你自己，返回[不能添加自己]
        if (user.getId().equals(myUserId)) {
            return SearchFriendsStatusEnum.NOT_YOURSELF.getStatus();
        }
        // 3. 搜索的朋友已经是你的好友，返回[该用户已经是你的好友]
        LambdaQueryWrapper<MyFriend> eq = Wrappers.lambdaQuery(MyFriend.class)
                .eq(MyFriend::getMyUserId, myUserId)
                .eq(MyFriend::getMyFriendUserId, user.getId());
        MyFriend myFriendsRel = myFriendsMapper.selectOne(eq);
        if (myFriendsRel != null) {
            return SearchFriendsStatusEnum.ALREADY_FRIENDS.getStatus();
        }
        return SearchFriendsStatusEnum.SUCCESS.getStatus();
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public User queryUserInfoByUsername(String username) {
        LambdaQueryWrapper<User> eq = Wrappers.lambdaQuery(User.class).eq(User::getUsername, username);
        return userMapper.selectOne(eq);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void sendFriendRequest(Long myUserId, String friendUsername) {
        // 根据用户名把朋友信息查询出来
        User friend = queryUserInfoByUsername(friendUsername);
        // 1. 查询发送好友请求记录表
        LambdaQueryWrapper<FriendsRequest> eq = Wrappers.lambdaQuery(FriendsRequest.class)
                .eq(FriendsRequest::getSendUserId, myUserId)
                .eq(FriendsRequest::getAcceptUserId, friend.getId());
        FriendsRequest friendRequest = friendsRequestMapper.selectOne(eq);
        if (friendRequest == null) {
            // 2. 如果不是你的好友，并且好友记录没有添加，则新增好友请求记录
            FriendsRequest request = new FriendsRequest();
            request.setId(IdWorker.getId());
            request.setSendUserId(myUserId);
            request.setAcceptUserId(friend.getId());
            request.setRequestDateTime(LocalDateTime.now());
            friendsRequestMapper.insert(request);
        }
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public List<FriendRequestVO> queryFriendRequestList(Long acceptUserId) {
        return userMapper.queryFriendRequestList(acceptUserId);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void deleteFriendRequest(Long sendUserId, Long acceptUserId) {
        LambdaQueryWrapper<FriendsRequest> eq = Wrappers.lambdaQuery(FriendsRequest.class)
                .eq(FriendsRequest::getSendUserId, sendUserId)
                .eq(FriendsRequest::getAcceptUserId, acceptUserId);
        friendsRequestMapper.delete(eq);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void passFriendRequest(Long sendUserId, Long acceptUserId) {
        saveFriends(sendUserId, acceptUserId);
        saveFriends(acceptUserId, sendUserId);
        deleteFriendRequest(sendUserId, acceptUserId);

        Channel sendChannel = ChannelUtil.get(sendUserId);
        if (sendChannel != null) {
            // 使用websocket主动推送消息到请求发起者，更新他的通讯录列表为最新
            DataContentDTO dataContentDTO = new DataContentDTO();
            dataContentDTO.setAction(MsgActionEnum.PULL_FRIEND.getType());

            sendChannel.writeAndFlush(
                    new TextWebSocketFrame(
                            JsonUtils.objectToJson(dataContentDTO)));
        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void saveFriends(Long sendUserId, Long acceptUserId) {
        MyFriend myFriends = new MyFriend();
        myFriends.setId(IdWorker.getId());
        myFriends.setMyFriendUserId(acceptUserId);
        myFriends.setMyUserId(sendUserId);
        myFriendsMapper.insert(myFriends);
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public List<MyFriendsVO> queryMyFriends(Long userId) {
        return userMapper.queryMyFriends(userId);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Long saveMsg(ChatMsgDTO chatMsgDTO) {
        ChatMsg msgDB = new ChatMsg();
        msgDB.setId(IdWorker.getId());
        msgDB.setAcceptUserId(chatMsgDTO.getReceiverId());
        msgDB.setSendUserId(chatMsgDTO.getSenderId());
        msgDB.setCreateTime(LocalDateTime.now());
        msgDB.setSignFlag(MsgSignFlagEnum.UN_SIGN.getType());
        msgDB.setMsg(chatMsgDTO.getMsg());
        chatMsgMapper.insert(msgDB);
        return msgDB.getId();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateMsgSigned(List<Long> msgIdList) {
        userMapper.batchUpdateMsgSigned(msgIdList);
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public List<ChatMsg> getUnReadMsgList(String acceptUserId) {
        LambdaQueryWrapper<ChatMsg> ew = Wrappers.lambdaQuery(ChatMsg.class)
                .eq(ChatMsg::getSignFlag, Boolean.FALSE)
                .eq(ChatMsg::getAcceptUserId, acceptUserId);
        return chatMsgMapper.selectList(ew);
    }
}
